﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Controls.Primitives;
using Bling.DSL;
using Bling.Properties;
using Bling.Shapes;
using Bling.Shaders;
using Bling.Geom;
using Bling.Animation;
using Bling.WPF;
using System.Windows.Shapes;
using System.Windows.Media.Effects;
using Bling.Util;
using Bling.Lighting;
using Bling.D3D;

namespace Bling.LightingTutorial {

  public class LightTest {

    public static readonly ImageSource Bump = Properties.Resources.bump.LoadBitmap();
    public static readonly ImageSource Base = Properties.Resources._base.LoadBitmap();

    public static readonly ImageSource MonkeyBump = Properties.Resources.MonkeyNormal.LoadBitmap();
    public static readonly ImageSource MonkeyBase = Properties.Resources.Monkey.LoadBitmap();

    public static readonly ImageSource Background = Properties.Resources.Green_Sea_Turtle.LoadBitmap();
    public static readonly ImageSource GlassBump = Properties.Resources.glassNormal.LoadBitmap();
    public static readonly ImageSource GlassBump_oxeye = Properties.Resources._2976_normal.LoadBitmap();

    public static readonly ImageSource BlockBump = Properties.Resources.Bump2spec_1_local.LoadBitmap();

    public static readonly ImageSource Metal = Properties.Resources.wall.LoadBitmap();
    public static readonly ImageSource Metal2 = Properties.Resources.metal.LoadBitmap();
    public static readonly ImageSource MetalOxidated = Properties.Resources.Oxidated.LoadBitmap();
    public static readonly ImageSource MetalBump = Properties.Resources.wall_norm.LoadBitmap();
    public static readonly ImageSource MetalBump2 = Properties.Resources._216_normal.LoadBitmap();

    public static readonly ImageSource Plastic = Properties.Resources._3177_diffuse.LoadBitmap();
    public static readonly ImageSource PlasticBump = Properties.Resources._3177_normal.LoadBitmap();

    public static readonly ImageSource Paper = Properties.Resources._4573_diffuse.LoadBitmap();
    public static readonly ImageSource PaperBump = Properties.Resources._4573_normal.LoadBitmap();

    public static readonly ImageSource buttonBump_up = Properties.Resources.button_normal.LoadBitmap();
    public static readonly ImageSource buttonBump_down = Properties.Resources.button_normal_2.LoadBitmap();

    public static readonly ImageSource curtainBump = Properties.Resources._4147_normal.LoadBitmap();
    public static readonly ImageSource curtainBase = Properties.Resources._4147_diffuse.LoadBitmap();
    public static readonly ImageSource curtainHeight = Properties.Resources._4147_bump.LoadBitmap();

    public static readonly ImageSource chocolateBump = Properties.Resources._303_normal.LoadBitmap();
    public static readonly ImageSource chocolateBase = Properties.Resources._303_diffuse.LoadBitmap();
    public static readonly ImageSource chocolateHeight = Properties.Resources._303_bump.LoadBitmap();

    public static readonly ImageSource panelBump = Properties.Resources._890_normal.LoadBitmap();
    public static readonly ImageSource panelBase = Properties.Resources._890_diffuse.LoadBitmap();
    public static readonly ImageSource panelHeight = Properties.Resources._890_bump.LoadBitmap();

    public static readonly ImageSource bubbleBump = Properties.Resources._505_normal.LoadBitmap();
    public static readonly ImageSource bubbleHeight = Properties.Resources._505_bump.LoadBitmap();
    public static readonly ImageSource bubbleBase = Properties.Resources._505_diffuse.LoadBitmap();

    public static readonly ImageSource woodBump = Properties.Resources._1319_normal.LoadBitmap();
    public static readonly ImageSource woodHeight = Properties.Resources._1319_bump.LoadBitmap();
    public static readonly ImageSource woodBase = Properties.Resources._1319_diffuse.LoadBitmap();

    public static readonly ImageSource capsuleBump = Properties.Resources._502_normal.LoadBitmap();
    public static readonly ImageSource capsuleBase = Properties.Resources._502_diffuse.LoadBitmap();

    public static readonly ImageSource Bulb = Properties.Resources.bulb.LoadBitmap();
    public static readonly ImageSource Sun = Properties.Resources.sun.LoadBitmap();

    public static readonly ImageSource CD = Properties.Resources.cd.LoadBitmap();
    public static readonly ImageSource Rainbow = Properties.Resources.rainbow.LoadBitmap();
    
    PointLightBl LightSource0;
    DirectionalLightBl LightSource1;
    SpotLightBl LightSource2;
    Point3DBl eyePos;
    Light LightStatus;

    private CanvasBl MainCanvas { get; set; }

    public LightTest(Canvas cvs, Light light) {
      MainCanvas = cvs;
      LightStatus = light;

      var slider1 = new LabelSliderBl(MainCanvas) { LeftTop = new PointBl(0, 30), Width = MainCanvas.Width, Minimum = 30.0, Maximum = 300.0, Value = 150.0, LabelName = "Height of eye", ZIndex = 100 };
      slider1.ToolTip = "Current eye's height: ".Bl() + slider1.Value;
      eyePos = new Point3DBl(MainCanvas.CenterSize, slider1.Value);

      ThumbBl thumb;
      if (LightStatus == Light.POINTLIGHT) {
        thumb = new ThumbBl(MainCanvas) { CanDrag = true, LeftTop = new PointBl(600, 400), Size = Bulb.Size(), Background = Colors.White, ZIndex = 100, Opacity = 0.001,};
        var bulb = new ImageBrush() { ImageSource = Bulb }.Bl();
        var newCanvas = new CanvasBl(MainCanvas) { CenterPosition = thumb.CenterPosition, Size = Bulb.Size(), Background = bulb, ZIndex = 99, };

        var slider2 = new LabelSliderBl(MainCanvas) { LeftTop = new PointBl(0, 60), Width = MainCanvas.Width, Minimum = 30.0, Maximum = 500.0, Value = 240.0, LabelName = "Height of lightSource", ZIndex = 100 };
        slider2.ToolTip = "Current light's height: ".Bl() + slider2.Value;

        LightSource0 = new PointLightBl() { 
          Position = new Point3DBl(thumb.CenterPosition, slider2.Value), 
          Color = Colors.White,
          Attenuation = { Constant = 5e-3, Linear = 2e-4, Quadratic = 2e-5 },
        };

      } else if (LightStatus == Light.SPOTLIGHT){
        thumb = new ThumbBl(MainCanvas) { CanDrag = true, LeftTop = new PointBl(600, 400), Size = Bulb.Size(), Background = Colors.White, ZIndex = 100, Opacity = 0.001,};
        var bulb = new ImageBrush() { ImageSource = Bulb }.Bl();
        var newCanvas = new CanvasBl(MainCanvas) { CenterPosition = thumb.CenterPosition, Size = Bulb.Size(), Background = bulb, ZIndex = 99, };

        var slider2 = new LabelSliderBl(MainCanvas) { LeftTop = new PointBl(0, 60), LabelName = "Height of lightSource", Width = MainCanvas.Width, Minimum = 30.0, Maximum = 500.0, Value = 240.0, ZIndex = 100 };
        slider2.ToolTip = "Current light's height: ".Bl() + slider2.Value;

        var slider3 = new LabelSliderBl(MainCanvas) { LeftTop = slider2.LeftBottom, LabelName = "Inner cone angle", Width = MainCanvas.Width, Minimum = 0.0, Maximum = 360.0, Value = 30.0, ZIndex = 100 };
        var slider4 = new LabelSliderBl(MainCanvas) { LeftTop = slider3.LeftBottom, LabelName = "Outer cone angle", Width = MainCanvas.Width, Minimum = 0.0, Maximum = 360.0, Value = 45.0, ZIndex = 100 };
        
        var pos = new Point3DBl(thumb.CenterPosition, slider2.Value);
        LightSource2 = new SpotLightBl() { 
          Position = pos, 
          Color = Colors.White, 
          InnerConeAngle = slider3.Value.ToDegrees(), 
          OuterConeAngle  = slider4.Value.ToDegrees(),
          Direction = (new Point3DBl(MainCanvas.CenterSize, 0) - pos).Normal,
         // Attenuation = { Constant = 5e-3, Linear = 2e-4, Quadratic = 2e-5 },
        };

      } else {
        thumb = new ThumbBl(MainCanvas) { CanDrag = true, LeftTop = MainCanvas.CenterSize, Size = Sun.Size(), Background = Colors.White, ZIndex = 100, Opacity = 0.001, };
        var sun = new ImageBrush() { ImageSource = Sun }.Bl();
        var newCanvas = new CanvasBl(MainCanvas) { CenterPosition = thumb.CenterPosition, Size = Sun.Size(), Background = sun, ZIndex = 99, };

        var slider2 = new LabelSliderBl(MainCanvas) { LeftTop = new PointBl(0, 60), Width = MainCanvas.Width, Minimum = 0.0, Maximum = 1.0, Value = 1.0, LabelName = "Lean of light direction", ZIndex = 100 };
        slider2.ToolTip = "Current light's lean: ".Bl() + slider2.Value;

        LightSource1 = new DirectionalLightBl() { Direction = new Point3DBl((thumb.CenterPosition - MainCanvas.CenterSize).Normal, slider2.Value), Color = Colors.Ivory };// 
      }
   }

    public void LightTest_Paper() {

      var thumb = new ThumbBl(MainCanvas) {
        LeftTop = new PointBl(0,160),
        CanDrag = true,
        Size = MainCanvas.Size,
        Opacity = 0.001,
        ZIndex = 10,
        Background = Brushes.Purple,
      };
      var newCanvas = new CanvasBl(MainCanvas) { CenterPosition = thumb.CenterPosition, Size = thumb.Size, Background = Brushes.White };

      if (LightStatus == Light.POINTLIGHT) {
      //var paperShader = new DiffusePaperLightShader() { 
        //LeftTop =  newCanvas.LeftTop, 
        //Size = newCanvas.Size, 
        //LightSource = LightSource0, 
        //PaperColor = Colors.CornflowerBlue.Bl(), 
        //attenuationCoefficient = new Point3DBl(5e-7, 7e-4, 0.5) 
    //};
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffuseColor(uv, Colors.CornflowerBlue.Bl(), LightSource0, newCanvas.LeftTop, newCanvas.Size);
        };
      } else  if (LightStatus == Light.SPOTLIGHT) {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffuseColor(uv, Colors.CornflowerBlue.Bl(), LightSource2, newCanvas.LeftTop, newCanvas.Size);
        };
      } else {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffuseColor(uv, Colors.CornflowerBlue.Bl(), LightSource1);
        };
      }
    }

    public void LightTest_Brick() {

      var normalMap = new ImageBrush() { ImageSource = Bump }.Bl();
      var baseMap = new ImageBrush() { ImageSource = Base }.Bl();

      var thumb = new ThumbBl(MainCanvas)
      {
          CenterPosition = MainCanvas.CenterSize,
          CanDrag = true,
          Size = Bump.Size(),
          Opacity = 0.001,
          ZIndex = 10,
          Background = Brushes.Purple,
      };
      var newCanvas = new CanvasBl(MainCanvas) { CenterPosition = thumb.CenterPosition, Size = Bump.Size(), Background = Brushes.White };

      var matBrick = new MaterialMapInfo{ MapInfo = MapInfo.DIFFUSE | MapInfo.NORMAL, DiffuseMap = baseMap, NormalMap = normalMap, MapLeftTop = newCanvas.LeftTop, MapSize = newCanvas.Size,};

      if (LightStatus == Light.POINTLIGHT) {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffuseSpecularColor(uv, baseMap, normalMap, LightSource0, eyePos, newCanvas.LeftTop, newCanvas.Size, 1.0, 0.12);
        };
      } else if (LightStatus == Light.SPOTLIGHT) {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffuseSpecularColor(uv, baseMap, normalMap, LightSource2, eyePos, newCanvas.LeftTop, newCanvas.Size, 1.0, 0.12);
        };
      } else {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffuseSpecularColor(uv, baseMap, normalMap, LightSource1, eyePos, newCanvas.LeftTop, newCanvas.Size, 1.0, 0.12);
        };
      }
    }
  
    public void LightTest_Monkey() {

      var normalMap = new ImageBrush() { ImageSource = MonkeyBump }.Bl();
      var baseMap = new ImageBrush() { ImageSource = MonkeyBase }.Bl();

      var thumb = new ThumbBl(MainCanvas) {
          CenterPosition = MainCanvas.CenterSize,
          CanDrag = true,
          Size = MonkeyBump.Size(),
          Opacity = 0.001,
          ZIndex = 10,
          Background = Brushes.Purple,
      };
      var newCanvas = new CanvasBl(MainCanvas) { CenterPosition = thumb.CenterPosition, Size = MonkeyBump.Size(), Background = Brushes.White};

      if (LightStatus == Light.POINTLIGHT) {
        newCanvas.Effect.Custom = (input, uv) => {
          var rgbColor = LightingTechniques.DiffuseSpecularColor(uv, baseMap, normalMap, LightSource0, eyePos, newCanvas.LeftTop, newCanvas.Size, 1.0, 0.7).ScRGB;
          return ColorBl.FromScRGB(baseMap[uv].ScA, rgbColor);
        };
      } else if (LightStatus == Light.SPOTLIGHT) {
        newCanvas.Effect.Custom = (input, uv) => {
          var rgbColor = LightingTechniques.DiffuseSpecularColor(uv, baseMap, normalMap, LightSource2, eyePos, newCanvas.LeftTop, newCanvas.Size, 1.0, 0.7).ScRGB;
          return ColorBl.FromScRGB(baseMap[uv].ScA, rgbColor);
        };
      } else {
        newCanvas.Effect.Custom = (input, uv) => {
          var rgbColor = LightingTechniques.DiffuseSpecularColor(uv, baseMap, normalMap, LightSource1, eyePos, newCanvas.LeftTop, newCanvas.Size, 1.0, 0.7).ScRGB;
          return ColorBl.FromScRGB(baseMap[uv].ScA, rgbColor);
        };
      }
    }
      
    public void LightTest_Glass() {

      var normalMap = new ImageBrush() { ImageSource = GlassBump }.Bl();
      var backgroundMap = new ImageBrush() { ImageSource = Background }.Bl();

      var newBackgound = new CanvasBl(MainCanvas) { CenterPosition = MainCanvas.CenterSize + new PointBl(0, 40), Size = Background.Size(), Background = backgroundMap };
      var thumb = new ThumbBl(MainCanvas) {
          CenterPosition = MainCanvas.CenterSize,
          CanDrag = true,
          Size = GlassBump.Size(),
          Opacity = 0.001,
          ZIndex = 10,
          Background = Brushes.Purple,
      };
      var slider = new LabelSliderBl(MainCanvas) { LeftBottom = new PointBl(0, MainCanvas.Height), Width = MainCanvas.Width, Minimum = 0.0, Maximum = 1.0, Value = 0.5, LabelName = "Transparency", ZIndex = 100 };

      var newCanvas = new CanvasBl(MainCanvas) { CenterPosition = thumb.CenterPosition, Size = GlassBump.Size(), Background = Brushes.White };
      if (LightStatus == Light.POINTLIGHT) {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.GlassColor(uv, Colors.LightBlue, backgroundMap, normalMap, LightSource0, eyePos, newCanvas.LeftTop, newCanvas.Size, 1.0, 0.9,
                  1.5, 2.5, newBackgound.LeftTop, newBackgound.Size, slider.Value);
        };
      } else if (LightStatus == Light.SPOTLIGHT) {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.GlassColor(uv, Colors.LightBlue, backgroundMap, normalMap, LightSource2, eyePos, newCanvas.LeftTop, newCanvas.Size, 1.0, 0.9,
                  1.5, 2.5, newBackgound.LeftTop, newBackgound.Size, slider.Value);
        };
      } else {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.GlassColor(uv, Colors.LightBlue, backgroundMap, normalMap, LightSource1, eyePos, newCanvas.LeftTop, newCanvas.Size, 1.0, 0.9,
                  1.5, 2.5, newBackgound.LeftTop, newBackgound.Size, slider.Value);
        };
      }
    }

    public void LightTest_Glass2()
    {

      var normalMap = new ImageBrush() { ImageSource = GlassBump_oxeye }.Bl();
      var backgroundMap = new ImageBrush() { ImageSource = Background }.Bl();

      var newBackgound = new CanvasBl(MainCanvas) { CenterPosition = MainCanvas.CenterSize + new PointBl(0, 40), Size = Background.Size(), Background = backgroundMap };
      var thumb = new ThumbBl(MainCanvas)
      {
          CenterPosition = MainCanvas.CenterSize,
          CanDrag = true,
          Size = GlassBump_oxeye.Size(),
          Opacity = 0.001,
          ZIndex = 10,
          Background = Brushes.Purple,
      };
      var slider = new LabelSliderBl(MainCanvas) { LeftBottom = new PointBl(0, MainCanvas.Height), Width = MainCanvas.Width, Minimum = 0.0, Maximum = 1.0, Value = 0.5, LabelName = "Transparency", ZIndex = 100 };
      
      var newCanvas = new CanvasBl(MainCanvas) { CenterPosition = thumb.CenterPosition, Size = GlassBump_oxeye.Size(), Background = Brushes.White };
      if (LightStatus == Light.POINTLIGHT) {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.GlassColor(uv, Colors.LightBlue, backgroundMap, normalMap, LightSource0, eyePos, newCanvas.LeftTop, newCanvas.Size, 1.0, 0.9,
                  1.5, 10, newBackgound.LeftTop, newBackgound.Size, slider.Value);
        };
      } else if (LightStatus == Light.SPOTLIGHT) {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.GlassColor(uv, Colors.LightBlue, backgroundMap, normalMap, LightSource2, eyePos, newCanvas.LeftTop, newCanvas.Size, 1.0, 0.9,
                  1.5, 10, newBackgound.LeftTop, newBackgound.Size, slider.Value);
        };
      } else {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.GlassColor(uv, Colors.LightBlue, backgroundMap, normalMap, LightSource1, eyePos, newCanvas.LeftTop, newCanvas.Size, 1.0, 0.9,
                  1.5, 10, newBackgound.LeftTop, newBackgound.Size, slider.Value);
        };
      }
    }

    public void LightTest_Metal() {

      var normalMap = new ImageBrush() { ImageSource = BlockBump }.Bl();
      var baseMap = new ImageBrush() { ImageSource = MetalOxidated }.Bl();

      var thumb = new ThumbBl(MainCanvas) {
          CenterPosition = MainCanvas.CenterSize,
          CanDrag = true,
          Size = BlockBump.Size(),
          Opacity = 0.001,
          ZIndex = 10,
          Background = Brushes.Purple,
      };
      var newCanvas = new CanvasBl(MainCanvas) { CenterPosition = thumb.CenterPosition, Size = BlockBump.Size(), Background = Brushes.White };
      if (LightStatus == Light.POINTLIGHT) {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffuseSpecularColor(uv, baseMap, normalMap, LightSource0, eyePos, newCanvas.LeftTop, newCanvas.Size, 1, 0.65);
        };
      } else if (LightStatus == Light.SPOTLIGHT) {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffuseSpecularColor(uv, baseMap, normalMap, LightSource2, eyePos, newCanvas.LeftTop, newCanvas.Size, 1, 0.65);
        };
      } else {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffuseSpecularColor(uv, baseMap, normalMap, LightSource1, eyePos, newCanvas.LeftTop, newCanvas.Size, 1, 0.65);
        };
      }
    }
        
    public void LightTest_Metal2() {

      var normalMap = new ImageBrush() { ImageSource = MetalBump }.Bl();
      var baseMap = new ImageBrush() { ImageSource = Metal }.Bl();

      var thumb = new ThumbBl(MainCanvas) {
          CenterPosition = MainCanvas.CenterSize,
          CanDrag = true,
          Size = MetalBump.Size(),
          Opacity = 0.001,
          ZIndex = 10,
          Background = Brushes.Purple,
      };
      var newCanvas = new CanvasBl(MainCanvas) { CenterPosition = thumb.CenterPosition, Size = MetalBump.Size(), Background = Brushes.White };

      if (LightStatus == Light.POINTLIGHT) {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffuseSpecularColor(uv, baseMap, normalMap, LightSource0, eyePos, newCanvas.LeftTop, newCanvas.Size, 1, 0.6);
        };
      } else if (LightStatus == Light.SPOTLIGHT) {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffuseSpecularColor(uv, baseMap, normalMap, LightSource2, eyePos, newCanvas.LeftTop, newCanvas.Size, 1, 0.6);
        };
      } else {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffuseSpecularColor(uv, baseMap, normalMap, LightSource1, eyePos, newCanvas.LeftTop, newCanvas.Size, 1, 0.6);
        };
      }    
    }
    
    public void LightTest_Metal3()
    {

      var normalMap = new ImageBrush() { ImageSource = MetalBump2 }.Bl();
      var baseMap = new ImageBrush() { ImageSource = Metal2 }.Bl();

      var thumb = new ThumbBl(MainCanvas)
      {
          CenterPosition = MainCanvas.CenterSize,
          CanDrag = true,
          Size = MetalBump2.Size(),
          Opacity = 0.001,
          ZIndex = 10,
          Background = Brushes.Purple,
      };
      var newCanvas = new CanvasBl(MainCanvas) { CenterPosition = thumb.CenterPosition, Size = MetalBump2.Size(), Background = Brushes.White };

      if (LightStatus == Light.POINTLIGHT) {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffuseSpecularColor(uv, baseMap, normalMap, LightSource0, eyePos, newCanvas.LeftTop, newCanvas.Size, 2, 0.9);
        };
      } else if (LightStatus == Light.SPOTLIGHT) {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffuseSpecularColor(uv, baseMap, normalMap, LightSource2, eyePos, newCanvas.LeftTop, newCanvas.Size, 2, 0.9);
        };
      } else {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffuseSpecularColor(uv, baseMap, normalMap, LightSource1, eyePos, newCanvas.LeftTop, newCanvas.Size, 2, 0.9);
        };
      } 
    }
    
    public void LightTest_Plastic() {

      var normalMap = new ImageBrush() { ImageSource = PlasticBump }.Bl();
      var baseMap = new ImageBrush() { ImageSource = Plastic }.Bl();

      var thumb = new ThumbBl(MainCanvas) {
          CenterPosition = MainCanvas.CenterSize,
          CanDrag = true,
          Size = PlasticBump.Size(),
          Opacity = 0.001,
          ZIndex = 10,
          Background = Brushes.Purple,
      };
      var newCanvas = new CanvasBl(MainCanvas) { CenterPosition = thumb.CenterPosition, Size = PlasticBump.Size(), Background = Brushes.White };

      if (LightStatus == Light.POINTLIGHT) {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffuseSpecularColor(uv, baseMap, normalMap, LightSource0, eyePos, newCanvas.LeftTop, newCanvas.Size, 4, 0.6);
        };
      } else if (LightStatus == Light.SPOTLIGHT) {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffuseSpecularColor(uv, baseMap, normalMap, LightSource2, eyePos, newCanvas.LeftTop, newCanvas.Size, 4, 0.6);
        };
      } else {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffuseSpecularColor(uv, baseMap, normalMap, LightSource1, eyePos, newCanvas.LeftTop, newCanvas.Size, 4, 0.6);
        };
      } 
    }

    public void LightTest_Button()
    {
      var normalMap_up = new ImageBrush() { ImageSource = buttonBump_up}.Bl();
      var normalMap_down = new ImageBrush() { ImageSource = buttonBump_down}.Bl();

      var thumb = new ThumbBl(MainCanvas)
      {
          CenterPosition = MainCanvas.CenterSize,
          CanDrag = true,
          Size = buttonBump_up.Size(),
          Opacity = 0.001,
          ZIndex = 10,
          Background = Brushes.Purple,
      };
      var newCanvas = new CanvasBl(MainCanvas) { CenterPosition = thumb.CenterPosition, Size = buttonBump_up.Size(), Background = Brushes.White };

      var slider3 = new SliderBl(MainCanvas) { LeftTop = new PointBl(0, 90), Width = MainCanvas.Width / 4, Minimum = 0.0, Maximum = 1.0, };

      if (LightStatus == Light.POINTLIGHT) {
        newCanvas.Effect.Custom = (input, uv) => {
          return slider3.Value.Lerp(LightingTechniques.DiffuseColor(uv, Colors.CornflowerBlue.Bl(), normalMap_up, LightSource0, newCanvas.LeftTop, newCanvas.Size),
                                    LightingTechniques.DiffuseColor(uv, Colors.CornflowerBlue.Bl(), normalMap_down, LightSource0, newCanvas.LeftTop, newCanvas.Size));
        };
      } else if (LightStatus == Light.SPOTLIGHT) {
        newCanvas.Effect.Custom = (input, uv) => {

          return slider3.Value.Lerp(LightingTechniques.DiffuseColor(uv, Colors.CornflowerBlue.Bl(), normalMap_up, LightSource2, newCanvas.LeftTop, newCanvas.Size),
                                    LightingTechniques.DiffuseColor(uv, Colors.CornflowerBlue.Bl(), normalMap_down, LightSource2, newCanvas.LeftTop, newCanvas.Size));
        };
      } else {
        newCanvas.Effect.Custom = (input, uv) => {
          return slider3.Value.Lerp(LightingTechniques.DiffuseColor(uv, Colors.CornflowerBlue.Bl(), normalMap_up, LightSource1),
                                    LightingTechniques.DiffuseColor(uv, Colors.CornflowerBlue.Bl(), normalMap_down, LightSource1));
        };
      }
    }
    
    public void LightTest_Curtain() {
      var normalMap = new ImageBrush() { ImageSource = curtainBump }.Bl();
      var baseMap = new ImageBrush() { ImageSource = curtainBase }.Bl();
      var heightMap = new ImageBrush() { ImageSource = curtainHeight }.Bl();

      var thumb = new ThumbBl(MainCanvas)
      {
          CenterPosition = MainCanvas.CenterSize,
          CanDrag = true,
          Size = curtainBump.Size(),
          Opacity = 0.001,
          ZIndex = 10,
          Background = Brushes.Purple,
      };
      var newCanvas = new CanvasBl(MainCanvas) { CenterPosition = thumb.CenterPosition, Size = curtainBump.Size(), Background = Brushes.White };

      //var curtainShader = new DiffuseSpecularLightShader() {
      // BaseMap = baseMap,
      // NormalMap = normalMap,
      // HeightMap = heightMap,
      // LightSource = LightSource0,
      // EyePos = eyePos,
      // LeftTop = newCanvas.LeftTop,
      // Size = newCanvas.Size,
      // attenuationCoefficient = new Point3DBl(5e-8, 5e-5, 0.9),
      // n = 3,
      // k = 0.7,
      //};
      //newCanvas.Effect.Custom = curtainShader.Shader;
      if (LightStatus == Light.POINTLIGHT) {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffuseSpecularColor(uv, baseMap, normalMap, LightSource0, eyePos, newCanvas.LeftTop, newCanvas.Size, 3, 0.7);
        };
      } else if (LightStatus == Light.SPOTLIGHT) {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffuseSpecularColor(uv, baseMap, normalMap, LightSource2, eyePos, newCanvas.LeftTop, newCanvas.Size, 3, 0.7);
        };
      } else {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffuseSpecularColor(uv, baseMap, normalMap, LightSource1, eyePos, newCanvas.LeftTop, newCanvas.Size, 3, 0.7);
        };
      }
    }

    public void LightTest_Chocolate(){
        var normalMap = new ImageBrush() { ImageSource = chocolateBump }.Bl();
        var baseMap = new ImageBrush() { ImageSource = chocolateBase }.Bl();
        var heightMap = new ImageBrush() { ImageSource = chocolateHeight }.Bl();

        var thumb = new ThumbBl(MainCanvas)
        {
            CenterPosition = MainCanvas.CenterSize,
            CanDrag = true,
            Size = chocolateBump.Size(),
            Opacity = 0.001,
            ZIndex = 10,
            Background = Brushes.Purple,
        };
        var newCanvas = new CanvasBl(MainCanvas) { CenterPosition = thumb.CenterPosition, Size = chocolateBump.Size(), Background = Brushes.White };

      if (LightStatus == Light.POINTLIGHT) {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffuseSpecularColor(uv, baseMap, normalMap, LightSource0, eyePos, newCanvas.LeftTop, newCanvas.Size, 5, 0.8);
        };
      } else if (LightStatus == Light.SPOTLIGHT) {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffuseSpecularColor(uv, baseMap, normalMap, LightSource2, eyePos, newCanvas.LeftTop, newCanvas.Size, 5, 0.8);
        };
      } else {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffuseSpecularColor(uv, baseMap, normalMap, LightSource1, eyePos, newCanvas.LeftTop, newCanvas.Size, 5, 0.8);
        };
      }
    }

    public void LightTest_Panel(){
      var normalMap = new ImageBrush() { ImageSource = panelBump }.Bl();
      var baseMap = new ImageBrush() { ImageSource = panelBase }.Bl();
      var heightMap = new ImageBrush() { ImageSource = panelHeight }.Bl();

      var thumb = new ThumbBl(MainCanvas)
      {
          CenterPosition = MainCanvas.CenterSize,
          CanDrag = true,
          Size = panelBump.Size(),
          Opacity = 0.001,
          ZIndex = 10,
          Background = Brushes.Purple,
      };
      var newCanvas = new CanvasBl(MainCanvas) { CenterPosition = thumb.CenterPosition, Size = panelBump.Size(), Background = Brushes.White };

      if (LightStatus == Light.POINTLIGHT) {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffuseSpecularColor(uv, baseMap, normalMap, LightSource0, eyePos, newCanvas.LeftTop, newCanvas.Size, 2, 0.8);
        };
      } else if (LightStatus == Light.SPOTLIGHT) {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffuseSpecularColor(uv, baseMap, normalMap, LightSource2, eyePos, newCanvas.LeftTop, newCanvas.Size, 2, 0.8);
        };
      } else {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffuseSpecularColor(uv, baseMap, normalMap, LightSource1, eyePos, newCanvas.LeftTop, newCanvas.Size, 2, 0.8);
        };
      }
    }

    public void LightTest_Bubble(){
        var normalMap = new ImageBrush() { ImageSource = bubbleBump }.Bl();
        var baseMap = new ImageBrush() { ImageSource = bubbleBase }.Bl();
        var heightMap = new ImageBrush() { ImageSource = bubbleHeight }.Bl();

        var thumb = new ThumbBl(MainCanvas)
        {
            CenterPosition = MainCanvas.CenterSize,
            CanDrag = true,
            Size = panelBump.Size(),
            Opacity = 0.001,
            ZIndex = 10,
            Background = Brushes.Purple,
        };
        var newCanvas = new CanvasBl(MainCanvas) { CenterPosition = thumb.CenterPosition, Size = panelBump.Size(), Background = Brushes.White };

      if (LightStatus == Light.POINTLIGHT) {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.SpecularColor(uv, normalMap, LightSource0, eyePos, newCanvas.LeftTop, newCanvas.Size, 10, 1.0)
                       + baseMap[uv];
        };
      } else if (LightStatus == Light.SPOTLIGHT) {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.SpecularColor(uv, normalMap, LightSource2, eyePos, newCanvas.LeftTop, newCanvas.Size, 10, 1.0)
                       + baseMap[uv];
        };
      } else {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.SpecularColor(uv, normalMap, LightSource1, eyePos, newCanvas.LeftTop, newCanvas.Size, 10, 1.0)
                       + baseMap[uv];
        };
      }
    }
    public void LightTest_Oldpaper(){
        var normalMap = new ImageBrush() { ImageSource = PaperBump }.Bl();
        var baseMap = new ImageBrush() { ImageSource = Paper }.Bl();

        var thumb = new ThumbBl(MainCanvas)
        {
            CenterPosition = MainCanvas.CenterSize,
            CanDrag = true,
            Size = PaperBump.Size(),
            Opacity = 0.001,
            ZIndex = 10,
            Background = Brushes.Purple,
        };
        var newCanvas = new CanvasBl(MainCanvas) { CenterPosition = thumb.CenterPosition, Size = PaperBump.Size(), Background = Brushes.White };

      if (LightStatus == Light.POINTLIGHT) {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffuseColor(uv, baseMap, normalMap, LightSource0, newCanvas.LeftTop, newCanvas.Size);
        };
      } else if (LightStatus == Light.SPOTLIGHT) {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffuseColor(uv, baseMap, normalMap, LightSource2, newCanvas.LeftTop, newCanvas.Size);
        };
      } else {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffuseColor(uv, baseMap, normalMap, LightSource1);
        };
      }
    }

    public void LightTest_Wood(){
        var normalMap = new ImageBrush() { ImageSource = woodBump }.Bl();
        var baseMap = new ImageBrush() { ImageSource = woodBase }.Bl();
        var heightMap = new ImageBrush() { ImageSource = woodHeight }.Bl();

        var thumb = new ThumbBl(MainCanvas)
        {
            CenterPosition = MainCanvas.CenterSize,
            CanDrag = true,
            Size = woodBump.Size(),
            Opacity = 0.001,
            ZIndex = 10,
            Background = Brushes.Purple,
        };
        var newCanvas = new CanvasBl(MainCanvas) { CenterPosition = thumb.CenterPosition, Size = woodBump.Size(), Background = Brushes.White };

        var slider = new LabelSliderBl(MainCanvas) {
          RightBottom = MainCanvas.Size - new PointBl(0, 30),
          Width = MainCanvas.Width, Minimum = 1, Maximum = 200, Value = 30, LabelName = "Height Scale", ZIndex = 100,
          IsEnabled = (LightStatus == Light.SPOTLIGHT) ? false : true,
        };

      if (LightStatus == Light.POINTLIGHT) {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffuseColor(uv, baseMap, heightMap, slider.Value, LightSource0, newCanvas.LeftTop, newCanvas.Size);
  //        return LightingTechniques.DiffuseSpecularColor(uv, baseMap, normalMap, LightSource0, eyePos, newCanvas.LeftTop, newCanvas.Size, 1, 0.5);
        };
      } else if (LightStatus == Light.SPOTLIGHT) {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffuseColor(uv, baseMap, heightMap, 30, LightSource2, newCanvas.LeftTop, newCanvas.Size);
  //        return LightingTechniques.DiffuseSpecularColor(uv, baseMap, normalMap, LightSource0, eyePos, newCanvas.LeftTop, newCanvas.Size, 1, 0.5);
        };
      } else {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffuseColor(uv, baseMap, heightMap, slider.Value, LightSource1, newCanvas.Size);
 //         return LightingTechniques.DiffuseSpecularColor(uv, baseMap, normalMap, LightSource1, eyePos, newCanvas.LeftTop, newCanvas.Size, 1, 0.5);
        };
      }
    }

    public void LightTest_Capsule() {
      var normalMap = new ImageBrush() { ImageSource = capsuleBump }.Bl();
      var baseMap = new ImageBrush() { ImageSource = capsuleBase }.Bl();

      var thumb = new ThumbBl(MainCanvas) {
        CenterPosition = MainCanvas.CenterSize,
        CanDrag = true,
        Size = capsuleBump.Size(),
        Opacity = 0.001,
        ZIndex = 10,
        Background = Brushes.Purple,
      };
      var newCanvas = new CanvasBl(MainCanvas) { CenterPosition = thumb.CenterPosition, Size = capsuleBump.Size(), Background = Brushes.White };

      if (LightStatus == Light.POINTLIGHT) {
        newCanvas.Effect.Custom = (input, uv) => {
          var RGBcolor = LightingTechniques.DiffuseSpecularColor(uv, baseMap, normalMap, LightSource0, eyePos, newCanvas.LeftTop, newCanvas.Size, 2, 0.8).ScRGB;
          return ColorBl.FromScRGB(baseMap[uv].ScA, RGBcolor);
        };
      } else if (LightStatus == Light.SPOTLIGHT) {
        newCanvas.Effect.Custom = (input, uv) => {
          var RGBcolor = LightingTechniques.DiffuseSpecularColor(uv, baseMap, normalMap, LightSource2, eyePos, newCanvas.LeftTop, newCanvas.Size, 2, 0.8).ScRGB;
          return ColorBl.FromScRGB(baseMap[uv].ScA, RGBcolor);
        };
      } else {
        newCanvas.Effect.Custom = (input, uv) => {
          var RGBcolor = LightingTechniques.DiffuseSpecularColor(uv, baseMap, normalMap, LightSource1, eyePos, newCanvas.LeftTop, newCanvas.Size, 2, 0.8).ScRGB;
          return ColorBl.FromScRGB(baseMap[uv].ScA, RGBcolor);
        };
      }
    }

    public void LightTest_CD() {
      var cd = new ImageBrush() { ImageSource = CD }.Bl();
      var rainbow = new ImageBrush() { ImageSource = Rainbow }.Bl();

      var thumb = new ThumbBl(MainCanvas) {
        CenterPosition = MainCanvas.CenterSize,
        CanDrag = true,
        Size = capsuleBump.Size(),
        Opacity = 0.001,
        ZIndex = 10,
        Background = Brushes.Purple,
      };
      var newCanvas = new CanvasBl(MainCanvas) { CenterPosition = thumb.CenterPosition, Size = CD.Size(), Background = cd };

      if (LightStatus == Light.POINTLIGHT) {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffractionCD(uv, input, rainbow, LightSource0, eyePos, newCanvas.LeftTop, newCanvas.Size);
        };
      } else if (LightStatus == Light.SPOTLIGHT) {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffractionCD(uv, input, rainbow, LightSource2, eyePos, newCanvas.LeftTop, newCanvas.Size);
        };
      } else {
        newCanvas.Effect.Custom = (input, uv) => {
          return LightingTechniques.DiffractionCD(uv, input, rainbow, LightSource1, eyePos, newCanvas.LeftTop, newCanvas.Size);
        };
      }
    }

    public void TestAll() {
      PointBl At = new PointBl(0, 0);
      At = new ButtonBl(MainCanvas) {
        LeftTop = At,
        Content = "Paper",
        Click = () => LightTest_Paper(),
      }.RightTop;

      At = new ButtonBl(MainCanvas) {
        LeftTop = At,
        Content = "Brick wall",
        Click = () => LightTest_Brick(),
      }.RightTop;

      At = new ButtonBl(MainCanvas) {
        LeftTop = At,
        Content = "Monkey",
        Click = () => LightTest_Monkey()
      }.RightTop;

      At = new ButtonBl(MainCanvas) {
        LeftTop = At,
        Content = "Glass grid",
        Click = () => LightTest_Glass()
      }.RightTop;

      At = new ButtonBl(MainCanvas) {
        LeftTop = At,
        Content = "Glass oxeye",
        Click = () => LightTest_Glass2()
      }.RightTop;


      At = new ButtonBl(MainCanvas) {
        LeftTop = At,
        Content = "Oxidated metal",
        Click = () => LightTest_Metal()
      }.RightTop;

      At = new ButtonBl(MainCanvas) {
        LeftTop = At,
        Content = "Rough metal plane",
        Click = () => LightTest_Metal2()
      }.RightTop;

      At = new ButtonBl(MainCanvas) {
        LeftTop = At,
        Content = "Alien Metal",
        Click = () => LightTest_Metal3()
      }.RightTop;

      At = new ButtonBl(MainCanvas) {
        LeftTop = At,
        Content = "plastic",
        Click = () => LightTest_Plastic()
      }.RightTop;

      At = new ButtonBl(MainCanvas) {
        LeftTop = At,
        Content = "Simple Button", IsEnabled = (LightStatus == Light.SPOTLIGHT)?false:true,
        Click = () => {
          LightTest_Button();
        }
      }.RightTop;

      At = new ButtonBl(MainCanvas) {
        LeftTop = At,
        Content = "Curtain",
        Click = () => LightTest_Curtain()
      }.RightTop;

      At = new ButtonBl(MainCanvas) {
        LeftTop = At,
        Content = "Chocolate",
        Click = () => LightTest_Chocolate()
      }.RightTop;

      At = new ButtonBl(MainCanvas) {
        LeftTop = At,
        Content = "Iron Panel",
        Click = () => LightTest_Panel()
      }.RightTop;

      At = new ButtonBl(MainCanvas) {
        LeftTop = At,
        Content = "Bubble Wrap",
        Click = () => LightTest_Bubble()
      }.RightTop;

      At = new ButtonBl(MainCanvas) {
        LeftTop = At,
        Content = "Wood",
        Click = () => LightTest_Wood()
      }.RightTop;

      At = new ButtonBl(MainCanvas) {
        LeftTop = At,
        Content = "old paper",
        Click = () => LightTest_Oldpaper()
      }.RightTop;

      At = new ButtonBl(MainCanvas) {
        LeftTop = At,
        Content = "Capsule",
        Click = () => LightTest_Capsule()
      }.RightTop;

      At = new ButtonBl(MainCanvas) {
        LeftTop = At,
        Content = "CD diffraction",
        Click = () => LightTest_CD()
      }.RightTop;

    }
  };

  public class PointLightTest : Canvas {
    public PointLightTest(){
      var lightTest = new LightTest(this, Light.POINTLIGHT);
      lightTest.TestAll();
    }
  };

  public class SpotLightTest : Canvas {
    public SpotLightTest(){
      var lightTest = new LightTest(this, Light.SPOTLIGHT);
      lightTest.TestAll();
    }
  };

  public class DirectionLightTest : Canvas {
    public DirectionLightTest() {
      var lightTest = new LightTest(this, Light.DIRECTIONALLIGHT);
      lightTest.TestAll();
    }
  };

}